package com.binc.testspring;

import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * FileName: TestHutool
 * Autho: binC
 * Date:  2023/2/16 9:57
 */
public class RASUtil {


        // 算法类别
        private final static String SIGN_TYPE = "RSA";
        // 算法位数
        private final static Integer KEY_SIZE = 2048;

        private final  static  String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwAWxoHmPZZ20rGF5tsbHnFFhaoD+FLt/brUGxEacbc4PDaU8Ez3iLG0+73pgjRP5gdlEJxNPDFxwcTLoOJSQf/Rho8bU1ml3noPDTCISq7cFy8Jut6zfZ83+M+Ve7FGaYKkoiComXshGBz91BAyJXbowvSAQzI9z8lnv1zyTXlUkjHL1DfVNHkSFVgoYXtnVLVpA6lTLs1VlLbLbaFqoOeU9raa3elUNAi0SIZG7Q/Dw5k/fCPRWDz9iKIp6tHYK+GsBCXgvspbmGPec02rxFE1FHT3FYY2DVfR8DAAoLSPfqb95OfGDNDTf6Q01P18Bfmhx4FUck4HHYS0jEZscZwIDAQAB";
        private final  static  String privateKey ="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDABbGgeY9lnbSsYXm2xsecUWFqgP4Uu39utQbERpxtzg8NpTwTPeIsbT7vemCNE/mB2UQnE08MXHBxMug4lJB/9GGjxtTWaXeeg8NMIhKrtwXLwm63rN9nzf4z5V7sUZpgqSiIKiZeyEYHP3UEDIldujC9IBDMj3PyWe/XPJNeVSSMcvUN9U0eRIVWChhe2dUtWkDqVMuzVWUtsttoWqg55T2tprd6VQ0CLRIhkbtD8PDmT98I9FYPP2Ioinq0dgr4awEJeC+yluYY95zTavEUTUUdPcVhjYNV9HwMACgtI9+pv3k58YM0NN/pDTU/XwF+aHHgVRyTgcdhLSMRmxxnAgMBAAECggEAbLGMZ2MH6aRIhh8zD2Qbz389XlUf/cpYiukLqISzvXAbk0TJ6bZo1W8NZe9mwdThsj+y1U+Xuk6FE36WdpiZ5uQFdPhyt9/BZ0f8f5b17J9QN5Oaqnu/hfnTf7rBbZGPilGWcOUzDQneofGooh8ajqR7PELvX2uAXVnNao+Od6FMQ9oP7u0XvhbNE5dIuUs0Ygja18uzc1Zv8sEd7LS5YKaVZy8j/TjtEgLgu54GXpxwtWf+cDuKlPErujAm5jtIkxnBoAMeV9ytCtCNNPAh1flYkTBETQ6DQ/lJRig58cwLvTi5OQQpPxzkL4C2sQbkEn9NqUn0kWAXCsNxGfqa6QKBgQDz+7QkM4mBsl+csRdBn3C+8qB9J/V/XANKF9C8G1Q5KJubmqsWrvU0qCDRi5SQqIBEA7pdAW/0HzkZIafNUH2uqj/647H2SFbLQbcAlrW088GufG0wL1u2b+3v/kMJOS+6NXQUv/Dwx7yQPfJXzL9tzybFQ7b5Lg5DfGUYVf5dpQKBgQDJetU+uKtAALazHmoai1nkuKEtiZ24rUrBI4aZS4CiFS/WYk+jOJSgphFXB+cOZ/DJeClYbfsSOQl5ySF7K6h8HZH1aiZEfbJiGi+yO801vHmg8rjK0fa6Ib+ZFFGVqStkAGRUOhdNLc13IalvTjCan8hEVEy5KaTlB95oj32MGwKBgQDQ/gjfAa6GBI9WH3P2aGchiZ/j1Xi7ccv3idLpbteEZr50Wda4BYJRartCA7hs+Yl1uWPIC1Uk3iIA3w1oF8yw83D+rlBg0LJYRaBGxtI7gJmlpzu4jLiY2+QLMdembO/vJ56Zr5jqB44EWKvgfah0nX9udoSjicn6EPJgGDldaQKBgQCB1JRLWYaItK0GWUf4GOnxWAQMqwwmcAymznSynZOjXlG4LRuySwiDSOANm/sJLnNb8AF8iUproLN5deEMVMK6T/e5FBDau8DSNJudl6mRwgUCcMYhdBEwOgUT6KL19NAQHayJFfHj+urWpKthHRp22RWc6lGSU8J9D4gDCsvVFwKBgFuVsbIdDT8mR3h5pBMdKWEDK54g+MasV/T5tLTtctmZ79+CTLts1Y5kOQle0M3VKZULnd9PFqRn/J7iFpF+4BVPvB+qDmv07v+fC0KnQBGvBg4xxAHthwdytSb6xYSWRKlvjrs3D6niIUEErSE32HOiXqYoZLyFBqEHWGutQyG1";

        // 测试加签
        @Test
        public void testSign(){
            Map<String,String> params = new HashMap<>();
            params.put("name","binc");
            params.put("pwd","123");
            String dateContent = getSignContent(params);

            //测试加签   加密类型RSA   加密算法 SHA256withRSA   如果想换的只更换这两个具体的之就行了
            String sign = RASUtil.sign256(dateContent.getBytes(StandardCharsets.UTF_8), privateKey);
            System.out.println("数据加签之后:sign="+sign);
            // 数据加签之后:sign=AY0xhLPiX1qfjRXfPjpGzWYNl3u9go3UrrlphPQ09EJmB3Eul4YwaYDgOVVoLU9TUb324zxxww89N/0Jr8TiTV2zGDj6yn4g6Q68fhjppXpaaj4db6qb9+7DajtIMUP9wpncsU7u8O+ve5J7mm9SnIgZeU7gteOQY7EDOKzFirZwwkwL1tWRWjTc+I1wr2ZTEsFdMyfXT+n0usEVlUDpD3p4a1f/4/udfdtpcgniCvCw6w8597jQdLtRsER8iIfQXFBmXBP8ArIebX0CnXrReFo0fxkL8PMqKDH5tceik6D+4MLpanCQWAAb5v/yFlT3lrl/YNUp4nlYRFHOuDeRlw==

        }

    // 测试验签
    @Test
    public void testVerify(){

        // 数据加签之后:sign=AY0xhLPiX1qfjRXfPjpGzWYNl3u9go3UrrlphPQ09EJmB3Eul4YwaYDgOVVoLU9TUb324zxxww89N/0Jr8TiTV2zGDj6yn4g6Q68fhjppXpaaj4db6qb9+7DajtIMUP9wpncsU7u8O+ve5J7mm9SnIgZeU7gteOQY7EDOKzFirZwwkwL1tWRWjTc+I1wr2ZTEsFdMyfXT+n0usEVlUDpD3p4a1f/4/udfdtpcgniCvCw6w8597jQdLtRsER8iIfQXFBmXBP8ArIebX0CnXrReFo0fxkL8PMqKDH5tceik6D+4MLpanCQWAAb5v/yFlT3lrl/YNUp4nlYRFHOuDeRlw==
        Map<String,String> params = new HashMap<>();
        params.put("name","binc");
        params.put("pwd","123");
        String dateContent = getSignContent(params);

        String sign="AY0xhLPiX1qfjRXfPjpGzWYNl3u9go3UrrlphPQ09EJmB3Eul4YwaYDgOVVoLU9TUb324zxxww89N/0Jr8TiTV2zGDj6yn4g6Q68fhjppXpaaj4db6qb9+7DajtIMUP9wpncsU7u8O+ve5J7mm9SnIgZeU7gteOQY7EDOKzFirZwwkwL1tWRWjTc+I1wr2ZTEsFdMyfXT+n0usEVlUDpD3p4a1f/4/udfdtpcgniCvCw6w8597jQdLtRsER8iIfQXFBmXBP8ArIebX0CnXrReFo0fxkL8PMqKDH5tceik6D+4MLpanCQWAAb5v/yFlT3lrl/YNUp4nlYRFHOuDeRlw==";

        boolean b = verify256(dateContent.getBytes(StandardCharsets.UTF_8), sign, publicKey);
        System.out.println(b);

    }




    // 真实数据排序加组合成串
    public static String getSignContent(Map<String, String> params) {
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        int index = 0;
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) {
                content.append((index == 0 ? "" : "&") + key + "=" + value);
                index++;
            }
        }
        return content.toString();
    }

        /**
         * 生成公私钥
         */
        public Map<String, String> getPublicPrivateKey() {
            Map<String, String> pubPriKey = new HashMap<>();
            KeyPair keyPair = KeyUtil.generateKeyPair(SIGN_TYPE, KEY_SIZE);
            String publicKeyStr = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
            String privateKeyStr = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
            pubPriKey.put("publicKey", publicKeyStr);
            pubPriKey.put("privateKey", privateKeyStr);
            return pubPriKey;
        }

        /**
         * 签名
         */
        public static String sign256(byte[] signData, String priKey) {
            try {
                byte[] keyBytes = Base64.getDecoder().decode(priKey);
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
                KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE);
                PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
                Signature si = Signature.getInstance(SignAlgorithm.SHA256withRSA.getValue());
                // 相当于  Signature si = Signature.getInstance("SHA256withRSA");
                si.initSign(privateKey);
                si.update(signData);
                byte[] sign = si.sign();
                return Base64.getEncoder().encodeToString(sign);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }

        /**
         * 验签
         */
        public static boolean verify256(byte[] dataBytes, String sign, String pubkey) {
            boolean flag = false;
            try {
                byte[] signByte = Base64.getDecoder().decode(sign);
                byte[] encodedKey = Base64.getDecoder().decode(pubkey);
                Signature verf = Signature.getInstance(SignAlgorithm.SHA256withRSA.getValue());
                KeyFactory keyFac = KeyFactory.getInstance(SIGN_TYPE);
                PublicKey puk = keyFac.generatePublic(new X509EncodedKeySpec(encodedKey));
                verf.initVerify(puk);
                verf.update(dataBytes);
                flag = verf.verify(signByte);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
            return flag;
        }




}